package com.backend.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.backend.system.beans.role.*;
import com.backend.system.common.PageBean;
import com.backend.system.dao.entity.MenuRole;
import com.backend.system.dao.entity.Role;
import com.backend.system.dao.entity.RoleUser;
import com.backend.system.dao.mapper.RoleMapper;
import com.backend.system.service.IMenuRoleService;
import com.backend.system.service.IRoleService;
import com.backend.system.service.IRoleUserService;
import com.backend.system.util.PageUtil;
import com.backend.system.util.StringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author backend-manage
 * @since 2024-04-02
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Resource
    private IRoleUserService roleUserService;

    @Resource
    private IMenuRoleService menuRoleService;

    /**
     * 通过用户ID查角色列表
     *
     * @param userId 用户ID
     * @return 角色列表
     */
    @Override
    public List<Role> getRolesByUserId(Long userId) {
        List<RoleUser> roleUsers = roleUserService.getRoleUsersByUserId(userId);
        if (CollectionUtils.isEmpty(roleUsers)) {
            return Collections.emptyList();
        }

        List<Long> roleIds = roleUsers.stream().map(RoleUser::getRoleId).distinct().toList();
        return this.listByIds(roleIds);
    }

    /**
     * 查询所有角色
     *
     * @return 响应
     */
    @Override
    public List<RoleQueryAllVO> listAll() {
        List<Role> roles = this.list();
        if (CollUtil.isEmpty(roles)) {
            return Collections.emptyList();
        }

        return roles.stream().map(this::buildVo).collect(Collectors.toList());
    }

    /**
     * 查询指定用户的所有角色（含已分配，未分配）
     *
     * @param req 请求入参
     * @return 响应
     */
    @Override
    public List<RoleQueryAllByUserVO> listAllByUser(RoleQueryAllByUserReq req) {
        List<RoleUser> roleUsers = roleUserService.getRoleUsersByUserId(req.getUserId());

        // 当前用户所拥有的角色
        Set<Long> roleIds = Collections.emptySet();
        if (!CollectionUtils.isEmpty(roleUsers)) {
            roleIds = roleUsers.stream().map(RoleUser::getRoleId).collect(Collectors.toSet());
        }

        // 查所有角色
        List<Role> roles = this.list();
        if (CollUtil.isEmpty(roles)) {
            return Collections.emptyList();
        }

        List<RoleQueryAllByUserVO> voList = new ArrayList<>();
        for (Role role : roles) {
            RoleQueryAllByUserVO vo = new RoleQueryAllByUserVO();
            BeanUtil.copyProperties(role, vo);
            // 设置用户是否拥有某个角色
            vo.setUserHasRole(CollUtil.isNotEmpty(roleIds) && roleIds.contains(role.getId()));
            voList.add(vo);
        }
        return voList;
    }

    /**
     * 通过菜单ID查寻当前菜单未拥有的角色
     *
     * @param menuId 菜单ID
     * @return 角色列表
     */
    @Override
    public List<Role> getRolesByMenuHasNot(Long menuId) {
        // 当前菜单已拥有的角色
        List<MenuRole> menuRoles = menuRoleService.getMenuRolesByMenuId(menuId);
        Set<Long> hasRoleIds = menuRoles.stream().map(MenuRole::getRoleId).collect(Collectors.toSet());

        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.notIn(CollUtil.isNotEmpty(hasRoleIds), Role::getId, hasRoleIds);
        queryWrapper.orderByAsc(Role::getId);
        return this.list(queryWrapper);
    }

    /**
     * 分页查询所有角色
     *
     * @param req 请求入参
     * @return 响应
     */
    @Override
    public PageBean<RoleQueryVO> listByPage(RoleQueryReq req) {
        // 分页查询
        IPage<Role> page = new Page<>(req.getPageNum(), req.getPageSize());
        LambdaQueryWrapper<Role> queryWrapper = buildQueryWrapper(req);
        IPage<Role> rolePage = this.getBaseMapper().selectPage(page, queryWrapper);

        // 处理查询结果
        List<Role> records = rolePage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageBean<>();
        }
        List<RoleQueryVO> resultList = records.stream().map(RoleQueryVO::convert).collect(Collectors.toList());
        return PageUtil.convertPage(rolePage, resultList);
    }

    private LambdaQueryWrapper<Role> buildQueryWrapper(RoleQueryReq req) {
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Objects.nonNull(req.getId()), Role::getId, req.getId());
        queryWrapper.eq(StringUtil.isNotBlank(req.getCode()), Role::getCode, req.getCode());
        queryWrapper.eq(StringUtil.isNotBlank(req.getRoleName()), Role::getRoleName, req.getRoleName());
        queryWrapper.orderByAsc(Role::getId);
        return queryWrapper;
    }

    private RoleQueryAllVO buildVo(Role role) {
        RoleQueryAllVO vo = new RoleQueryAllVO();
        BeanUtil.copyProperties(role, vo);
        return vo;
    }
}
